﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data.OleDb;
using System.Drawing;
using System.Data;
using System.IO;
using System.Text;
using System.Windows.Forms;
using Microsoft.Office.Interop.Excel;
using System.Reflection;
using System.Threading;


namespace TrackingAssist.WebTrends
{
    public partial class WebTrendsView : UserControl
    {
        private ListViewColumnSorter lvwColumnSorter;
        public static IList<WebTrends> WebTrendsSpecList = new List<WebTrends>();
        public static IList<WebTrends> CapturedWebTrendsList = new List<WebTrends>();
        public static IList<WebTrends> MissedWebTrendsTracking = new List<WebTrends>();
      

        public static bool EnableUrlDecode = false;
        public static bool EnableAtlasAssist = false;
        public static bool IsRecording = false;
        private int capturedAtlasCount = 0;

        private string _project = "UnknownProject";
        private string atlasSpecPath = null;
        public static bool EnableComScoreAssist = false;

        public WebTrendsView()
        {
            InitializeComponent();
            LoadingLabel.Visible = false;
            this.lsvTrackingList.SmallImageList = ResourceManager.GetIconList();
            lsvTrackingList.ShowItemToolTips = true;
           
            lvwColumnSorter = new ListViewColumnSorter();
            this.lsvTrackingList.ListViewItemSorter = lvwColumnSorter;
            
        }

        /// <summary>
        /// Add a row to listview
        /// </summary>
        /// <param name="tracking"></param>
        public void AddCapturedWebTrends(WebTrends tracking)
        {
            ListViewItem item = new ListViewItem();
            item.UseItemStyleForSubItems = false;
            item.SubItems.Clear();
            item.SubItems[0].Text = (++capturedAtlasCount).ToString();
            item.SubItems.Add(tracking.Id);
            addSubItemForCapturedTracking(item, tracking.Section);
            addSubItemForCapturedTracking(item, tracking.Location);
            addSubItemForCapturedTracking(item, tracking.Action);
            addSubItemForCapturedTracking(item, tracking.ActionName);
            addSubItemForCapturedTracking(item, tracking.Var1);
            addSubItemForCapturedTracking(item, tracking.Var2);
            addSubItemForCapturedTracking(item, tracking.Var3);
            
            item.SubItems.Add(tracking.Language);
            item.SubItems.Add(tracking.Market);
            item.SubItems.Add(tracking.Browser);
            item.SubItems.Add(tracking.VideoTime);
            item.SubItems.Add(tracking.Time);
            item.SubItems.Add(tracking.FullUrl);
            _project = tracking.Project;
            switch (tracking.Match)
            {
                case MatchResult.Match:
                    item.ImageIndex = (int)AppIcons.Pass;
                    break;
                case MatchResult.NotMatch:
                    item.ImageIndex = (int)AppIcons.Fail;
                    break;
                case MatchResult.UnKnown:
                    item.ImageIndex = (int) AppIcons.UnKnown;
                    break;
                default: break;
            }

            if (!string.IsNullOrEmpty(tracking.Description))
                item.ToolTipText = tracking.Description;
            
            lsvTrackingList.Items.Add(item);

            //Add to caputured atlas list
            CapturedWebTrendsList.Add(tracking);
        }

        /// <summary>
        /// Add a row to listview
        /// </summary>
        /// <param name="tracking"></param>


        /// <summary>
        /// Add subitem to ListViewItem 
        /// </summary>
        /// <param name="lsvItem"></param>
        /// <param name="atlasItem"></param>
        private void addSubItemForCapturedTracking(ListViewItem lsvItem, WebTrendsItem atlasItem)
        {
            if (!atlasItem.IsMatch)
            {
                lsvItem.SubItems.Add(atlasItem.Value, Color.Red, Color.White, null);
            }
            else if (atlasItem.IsDynamic)
            {
                lsvItem.SubItems.Add(atlasItem.Value, Color.Blue, Color.White, null);
            }
            else
                lsvItem.SubItems.Add(atlasItem.Value);
                
        }

        /// <summary>
        /// Bind filter checklistbox items
        /// </summary>
        private void bindFilterListDataSource()
        {
            FilterType selectedFilterType = getSelectFilterType();
            IFilter filter = FilterFactory.CreateInstance(selectedFilterType);
            this.clbFilter.Items.Clear();

            var dataSource = filter.GetDataSource();
            if (dataSource != null)
            {
                foreach (var value in dataSource)
                {
                    this.clbFilter.Items.Add(value, CheckState.Unchecked);
                }
            }
        }

        /// <summary>
        /// Get selected filter type
        /// </summary>
        /// <returns></returns>
        private FilterType getSelectFilterType()
        {
            if (this.rdbSection.Checked)
                return FilterType.Secion;
            else
                return FilterType.Location;
        }

        /// <summary>
        /// get file type by file name
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        private string getFileType(string fileName)
        {
            string[] items = fileName.Split(new char[] { '.' });
            return items[items.Length - 1];
        }

        #region CONTROL EVENTS
        /// <summary>
        /// Capture tracking checkbox check change
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void chbEnableAtlasAssist_CheckedChanged(object sender, EventArgs e)
        {
            if (chbEnableAtlasAssist.Checked)
                EnableAtlasAssist = true;
            else
                EnableAtlasAssist = false;
        }

        /// <summary>
        /// Url decode check change
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void chbEnableUrlDecode_CheckedChanged(object sender, EventArgs e)
        {
            if (this.chbEnableUrlDecode.Checked)
                EnableUrlDecode = true;
            else
                EnableUrlDecode = false;
        }

        /// <summary>
        /// Load spec button click
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnLoadFile_Click(object sender, EventArgs e)
        {
            LoadingLabel.Visible = true;
            Thread thread = new Thread(new ThreadStart(LoadingExcelFile));
            thread.SetApartmentState(ApartmentState.STA);
            thread.IsBackground = true;
            thread.Start();  
        }

        public void LoadingExcelFile()
        {
            this.FileNameLabel.Invoke((System.Action)delegate() { FileNameLabel.Text = ""; });
            btnLoadFile.Enabled = false;
            openFileDialog.Filter = "Spec Files(*.xlsx;*.xls;*.xml)|*.xlsx;*.xls;*.xml";
            openFileDialog.RestoreDirectory = true;
            openFileDialog.FilterIndex = 1;
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                atlasSpecPath = openFileDialog.FileName;
                if (WebTrendsSpecList != null)
                    WebTrendsSpecList.Clear();


                IWebTrendsSpec specInstance;
                if (string.Equals(getFileType(atlasSpecPath), "xml"))
                {
                    specInstance = WebTrendsSpecFactory.CreateInstance(WebTrendsSpecType.Xml);
                }
                else
                {
                    specInstance = WebTrendsSpecFactory.CreateInstance(WebTrendsSpecType.Excel);
                }

                //extract atlas and comscore spec from tracking spec
                specInstance.LoadSpecFromFile(atlasSpecPath, out WebTrendsSpecList);

                if (WebTrendsSpecList != null && WebTrendsSpecList.Count > 0)
                {

                    this.tabTrackingType.SelectedTab = tabAtlas;
                    bindFilterListDataSource();
                    this.btnShowMissing.Enabled = true;
                    this.btnClearMissing.Enabled = true;
                    this.btnExport.Enabled = true;
                    this.chbSendMail.Enabled = true;
                    this.LoadingLabel.Invoke((System.Action)delegate() { LoadingLabel.Image = null; });
                    this.LoadingLabel.Invoke((System.Action)delegate() { LoadingLabel.Text = "Loaded!"; });
                    this.FileNameLabel.Invoke((System.Action)delegate() { FileNameLabel.Text = openFileDialog.FileName.ToString(); });
                    //MessageBox.Show("Tracking spec is loaded");

                }
                else
                {
                    this.LoadingLabel.Invoke((System.Action)delegate() { LoadingLabel.Image = null; });
                    this.LoadingLabel.Invoke((System.Action)delegate() { LoadingLabel.Text = "error while Loading!"; });
                    //MessageBox.Show("error while loading spec!");
                }

            }
            btnLoadFile.Enabled = true;
        }

        /// <summary>
        /// Clear session button click event handler
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnClear_Click(object sender, EventArgs e)
        {
            this.lsvTrackingList.Items.Clear();
            CapturedWebTrendsList.Clear();
            MissedWebTrendsTracking.Clear();
            this.capturedAtlasCount = 0;
        }

        /// <summary>
        /// Section filter CheckedChanged
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void rdbSection_CheckedChanged(object sender, EventArgs e)
        {
            bindFilterListDataSource();
        }

        /// <summary>
        /// Location filter CheckedChanged
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void rdbLocation_CheckedChanged(object sender, EventArgs e)
        {
            bindFilterListDataSource();
        }

        /// <summary>
        /// Right menu- copy
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void menuItemCopy_Click(object sender, EventArgs e)
        {
            if (this.tabTrackingType.SelectedTab == this.tabAtlas)
            {
                if (this.lsvTrackingList.SelectedItems.Count <= 0)
                    return;

                if (this.lsvTrackingList.SelectedItems[0].SubItems.Count >= 15)
                {
                    string data = this.lsvTrackingList.SelectedItems[0].SubItems[14].Text;
                    Clipboard.SetText(data);
                }

            }  
        }

        /// <summary>
        /// show missed tracking click
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnShowMissing_Click(object sender, EventArgs e)
        {
            IList<WebTrends> specAtlasList = getFilterdSpecList();
            if (specAtlasList==null)
                return;

            btnClearMissing_Click(null, null);

            foreach (WebTrends spec in specAtlasList)
            {
                bool captured = false;
                if (CapturedWebTrendsList != null)
                {
                    foreach (WebTrends actual in CapturedWebTrendsList)
                    {
                        if (string.Equals(spec.Id, actual.Id) && ((actual.Match == MatchResult.Match)||(actual.Match == MatchResult.NotMatch)))
                        {
                            captured = true;
                            break;
                        }
                    }
                }

                if (!captured)
                {
                    MissedWebTrendsTracking.Add(spec);
                }
            }


            foreach (WebTrends atlas in MissedWebTrendsTracking)
            {
                ListViewItem item = new ListViewItem();
                item.UseItemStyleForSubItems = false;
                item.ImageIndex = (int)AppIcons.Miss;
                item.SubItems.Clear();
                item.SubItems[0].Text = "M";
                addSubitemForMissedTracking(item, atlas.Id);
                addSubitemForMissedTracking(item, atlas.Section.Value);
                addSubitemForMissedTracking(item, atlas.Location.Value);
                addSubitemForMissedTracking(item, atlas.Action.Value);
                addSubitemForMissedTracking(item, atlas.ActionName.Value);
                addSubitemForMissedTracking(item, atlas.Var1.Value);
                addSubitemForMissedTracking(item, atlas.Var2.Value);
                addSubitemForMissedTracking(item, atlas.Var3.Value);
                lsvTrackingList.Items.Add(item);
            }
        }

        /// <summary>
        /// add Subitem For Missed Tracking
        /// </summary>
        /// <param name="item"></param>
        /// <param name="value"></param>
        private void addSubitemForMissedTracking(ListViewItem item, string value)
        {
            var foreColor = Color.Blue;
            var backColor = Color.White;
            item.SubItems.Add(value, foreColor, backColor, null);
        }

        /// <summary>
        /// clear missed tracking click
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnClearMissing_Click(object sender, EventArgs e)
        {
            MissedWebTrendsTracking.Clear();

            for (int i = lsvTrackingList.Items.Count - 1; i >= 0; i--)
            {
                if (lsvTrackingList.Items[i].ImageIndex == (int)AppIcons.Miss)
                {
                    lsvTrackingList.Items[i].Remove();
                }
            }
        }

        /// <summary>
        /// check all filter items
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnCheckAll_Click(object sender, EventArgs e)
        {

        }

        /// <summary>
        /// uncheck all fiter items
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnUncheckAll_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < this.clbFilter.Items.Count; i++)
            {
                this.clbFilter.SetItemChecked(i, false);
            }
        }

        /// <summary>
        /// listview column click
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void lsvTrackingList_ColumnClick(object sender, ColumnClickEventArgs e)
        {
            if (e.Column == lvwColumnSorter.SortColumn)
            {
                if (lvwColumnSorter.Order == SortOrder.Ascending)
                {
                    lvwColumnSorter.Order = SortOrder.Descending;
                }
                else
                {
                    lvwColumnSorter.Order = SortOrder.Ascending;
                }
            }
            else
            {
                lvwColumnSorter.SortColumn = e.Column;
                lvwColumnSorter.Order = SortOrder.Ascending;
            }

            this.lsvTrackingList.Sort();
        }

        /// <summary>
        /// Export the test result to the original tracking spec, and send the result via email if email address is inputted
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnExport_Click(object sender, EventArgs e)
        {
            try
            {
                DateTime dateTime = System.DateTime.Now;
                if (string.IsNullOrEmpty(atlasSpecPath))
                {
                    MessageBox.Show("you didn't load the tracking spec file,please upload the spec file first");
                    return;
                }
                if (lsvTrackingList.Items.Count==0)
                {
                    MessageBox.Show("there is no result to export");
                    return;
                }
 
                WriteAtlas.MatchResulttoAtlas(atlasSpecPath, lsvTrackingList);
                if (chbSendMail.Checked)
                {
                    SendMail sendMail = new SendMail(Environment.UserName + "@microsoft.com", this.txtReceiver.Text, string.Empty, string.Format(WebTrendsConsts.MAIL_TITLE, _project), string.Format(WebTrendsConsts.MAIN_BODY, _project), false);
                    sendMail.SmtpServer = WebTrendsConsts.SMTP_SERVER;
                    //sendMail.Attach(filename);
                    sendMail.Attach(atlasSpecPath);
                    sendMail.Send();
                    MessageBox.Show("Send the result Successfully!");
                    return;
                }

                MessageBox.Show(string.Format("Export Successfully!\n\rPlease find the result at {0} ",atlasSpecPath));
            }
            catch (Exception ex)
            {
                MessageBox.Show(string.Concat("Exception in export:", ex.Message));
            }
        }




        private IList<WebTrends> getFilterdSpecList()
        {
            if (this.clbFilter.CheckedItems.Count <= 0)
            {
                MessageBox.Show("Please select Section/Location items!");
                return null;
            }

            IList<string> selectedFilter = new List<string>();
            foreach (var item in this.clbFilter.CheckedItems)
            {
                selectedFilter.Add(item.ToString());
            }

            FilterType filterType = getSelectFilterType();
            IFilter filter = FilterFactory.CreateInstance(filterType);
            return filter.GetFiltedSpecItems(selectedFilter);
        }
        #endregion

        private void chbSendMail_CheckedChanged(object sender, EventArgs e)
        {
            if(this.chbSendMail.Checked)
            {
                this.btnExport.Text = "Send Mail";
                this.txtReceiver.Enabled = true;
            }
            else
            {
                this.btnExport.Text = "Export Results to tracking spec";
                this.txtReceiver.Enabled = false;
            }
        }

        private static bool alternateFlag = true;

        private void checkFilter_CheckedChanged(object sender, EventArgs e)
        {
            if (checkFilter.Checked == true)
            {
                for (int i = 0; i < this.clbFilter.Items.Count; i++)
                {
                    this.clbFilter.SetItemChecked(i, true);
                }
            }
            else 
            {
                for (int i = 0; i < this.clbFilter.Items.Count; i++)
                {
                    this.clbFilter.SetItemChecked(i, false);
                }
            }
        }
    

        private void tabTrackingType_SelectedIndexChanged(object sender, EventArgs e)
        {

            if (this.tabTrackingType.SelectedTab == this.tabAtlas)
            {
                EnableComScoreAssist = false;
                if (this.chbEnableAtlasAssist.Checked)
                    EnableAtlasAssist = true;
            }
        }


        //filter the result
        private void clbFilter_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.lsvTrackingList.Items.Clear();
            string filterByValue = this.rdbSection.Checked ? "Section" : "Location";
            string filterItem = string.Empty;
            for (int i = 0; i < this.clbFilter.SelectedItems.Count; i++)
            {
                filterItem += this.clbFilter.SelectedItems[i].ToString();
            }

            IList<WebTrends> filterlist = ShowItemsByFilter(filterByValue, filterItem);
            foreach (WebTrends atlas in filterlist)
            {
                AddCapturedWebTrends(atlas);
            }
            
        }

        private IList<WebTrends> ShowItemsByFilter(string filterByValue, string filterItem)
        {
            IList<WebTrends> showlist = new List<WebTrends>();
            switch (filterByValue)
            {
                case "Section":
                    foreach (WebTrends atlas in CapturedWebTrendsList)
                    {
                        //if (string.Equals(atlas.Section.Value, filterItem))
                        if (atlas.Section.Value.Contains(filterItem))
                            showlist.Add(atlas);
                    }
                    break;
                case "Location":
                    foreach (WebTrends atlas in CapturedWebTrendsList)
                    {
                        if (string.Equals(atlas.Location.Value, filterItem))
                            showlist.Add(atlas);
                    }
                    break;
                default:
                    break;

            }
            return showlist;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(atlasSpecPath))
            {
                MessageBox.Show("you didn't load the tracking spec file,please upload the spec file first");
                return;
            }
            if (lsvTrackingList.Items.Count == 0)
            {
                MessageBox.Show("there is no result to export");
                return;
            }
            int number = WriteAtlas.CopyLinksToExcel(atlasSpecPath, CapturedWebTrendsList);
            MessageBox.Show("Copied " + number + " links!");


        }


    }
}